﻿using System;
using System.Diagnostics.Contracts;
using System.IO;
using OpenLS.Spreadsheet.Formats.Biff.Tokens;

namespace OpenLS.Spreadsheet.Formats.Biff.Records
{
    internal class ObjFmla
    {
        private ObjectParsedFormula _fmla;
        private byte[] padding;
        private PictFmlaEmbedInfo embedInfo;

        public void Read(BinaryReader reader, bool inFtPictFmla)
        {
            ushort cbFmla = reader.ReadUInt16();
            var position = reader.BaseStream.Position;
            if (cbFmla > 0)
            {
                _fmla = new ObjectParsedFormula();

                _fmla.Read(new FormulaReadContext(reader, FormulaReadContextType.Default));
            }
            if (inFtPictFmla)
            {
                this.embedInfo = new PictFmlaEmbedInfo();
                this.embedInfo.Read(reader);
            }
            var diff = cbFmla - (reader.BaseStream.Position - position);
            Contract.Assert(diff >= 0);
            if (diff > 0)
                this.padding = reader.ReadBytes((int) diff);
        }
        public void Write(BinaryWriter writer)
        {
            Write(writer, FormulaReadContextType.Default);
        }
        public void Write(BinaryWriter writer, FormulaReadContextType type)
        {
            ushort cbFmla;
            if (_fmla == null)
            {
                cbFmla = 0;
            }
            else
            {
                cbFmla = _fmla.TotalTokenByteLength(type);
            }
            writer.Write(cbFmla);
            if (_fmla != null)
                _fmla.Write(new FormulaWriteContext(writer, type));
            if (padding != null)
                writer.Write(padding);
        }
    }

    internal class PictFmlaEmbedInfo
    {
        private byte cbClass;
        private XLUnicodeStringNoCch strClass;

        public void Read(BinaryReader reader)
        {
            var ttb = reader.ReadByte();
            Contract.Assert(0x03 == ttb);
            this.cbClass = reader.ReadByte();
            var reserved = reader.ReadByte();
            Contract.Assert(reserved == 0);
            if (cbClass > 0)
            {
                this.strClass = new XLUnicodeStringNoCch();
                this.strClass.Read(reader, cbClass);
            }
        }
    }
}